// develop_text_tree.cpp : Defines the entry point for the console application.
//

//#include "stdafx.h"

#include <assert.h>
#include <stdexcept>
#include <string>
#include <vector>
#include <iostream>

#include <ksstr/ksstr.h> 



class TextTree {
public:


	class Node {
	private:

		std::vector<Node> m_child;
	
	public:

		Node() {}
		Node(const std::string& _name, const std::string& _text)
		{
			m_name = _name;
			m_text = _text;

		}

		std::string m_name;
		std::string m_text;


		Node& append_child( Node& n )
		{
			m_child.push_back( n );  
		}

		Node& append_child(const std::string& name, const std::string& text)
		{
			Node n(name, text);
			m_child.push_back(n);
			return m_child.at( m_child.size()-1 );
		}

		Node& operator [] (int index)
		{
			return m_child.at(index);
		}

		size_t num_childr() const 
		{
			return m_child.size();
		}

		void to_text_recurse(int& level, std::string& text) const throw(std::runtime_error)
		{
			if(m_name.empty() )
			{
				throw std::runtime_error("empty name");
			}

			for(int ct=0; ct<level; ct++) text += "\t";	//< add tabs
			text += "<text=";
			text += m_name;
			text += ">";

			if(m_text.empty())
			{
				throw std::runtime_error("text empty");
			}

			text += "\n";
			text += m_text;
			text += "\n";

			//
			for(int ct=0; ct<level; ct++) text += "\t";

			level++;
			for(size_t c=0; c<m_child.size(); c++)
			{
				m_child[c].to_text_recurse( level, text );
			}
			level--;
 
			for(int ct=0; ct<level; ct++) text += "\t";	//< add tabs
			text += "</text>\n\n";
		}

		void num_items_recurse(int& level, int& res) const
		{
			res += 1; //< self

			level++;
			for(size_t c=0; c<m_child.size(); c++)
			{
				m_child[c].num_items_recurse(level, res);
			}
			level--;

		}


 
	};

	Node root;

	TextTree(const std::string& root_name, const std::string& root_text) 
		:root(root_name, root_text) 
	{

	}

	~TextTree() {}

	void to_text(std::string& text) const throw(std::runtime_error);
	int num_items() const;
 
};


//===========================================================

void TextTree::to_text(std::string& text) const throw(std::runtime_error)
{
	int level = 0;
	root.to_text_recurse(level, text);
}

int TextTree::num_items() const
{
	int level = 0;
	int res = 0;
	root.num_items_recurse(level, res);
	return res;
}


//------------------------------------------

 // s:\Visual Studio 2005\Projects\develop_text_tree\develop_text_tree\develop_text_tree.cpp

#if 0
int _tmain(int argc, _TCHAR* argv[])
{

   
	std::string dest;
	TextItemsHolder ti;
	ti.Add("aaa" , "aaaaaaaaaaaaaaaaaaa");
	ti.Add("bbb" , "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
	ti.Add("cccc" , "cccccccccccccccc");
	ti.Add("ddd" , "dddddddddddddddddddddddddddddddd");

	ti.WriteToText(dest);
	std::cout << dest << std::endl;
	std::cout << "\n\n" << std::endl;

	int _ddd = 0;

	ti.Clear();
	ti.ReadFromText(dest);
	dest = "";
	ti.WriteToText(dest);

	std::cout << "\n\n\n" << std::endl;
	std::cout << dest << std::endl;
	std::cout << "\n\n" << std::endl;

   int bb = 0;





   //----------------------------------
   TextTree tt("name1", "name1_text");
   tt.root.append_child( "name2", "name2_text" );
   tt.root.append_child( "name3", "name3_text" );
   tt.root.append_child( "name4", "name4_text" );
   TextTree::Node& n = tt.root.append_child( "name5", "name5_text" );
	n.append_child("name6", "name6_text");
	n.append_child("name7", "name7_text");
	TextTree::Node& n2 = n.append_child("name8", "name8_text");
	n2.append_child("name9","name9_text");
	n2.append_child("name10","name10_text");

	std::string text ;
	tt.to_text(text);
	



	std::cout << text << std::endl;
	std::cout << "\n\n" << std::endl;
	system("pause");

	int num = tt.num_items();
	return 0;
}

#endif 


